Computer security is often dependent on being able to predict the behavior of software components. In general, the security of a system may flow from the premise that a known program whose behavior is understood, which proceeds from a known good state, will act in a predictable manner. Conversely, the thwarting of security—which may involve getting a computer system to behave in ways that are outside the contemplation of its designer—can generally be realized by replacing or changing a known program, or running it in a state in which its behavior is not understood. Thus, one aspect of providing security for a computing environment includes verifying that a known program is being used, and that it is proceeding from a known good state.
One area where predictability of behavior is particularly important is in the loading of an operating system and its components. Although the operating system itself may be designed to provide some level of trustworthiness as to its behavior, the time before such an operating system has been loaded is a time when the system is particularly vulnerable to attack, since the infrastructure that protects the operating system from attacks may not have been established yet (or may be in the process of being established). Thus, ensuring that the operating system loads in a predictable way is important for protecting the operating system from certain classes of attacks.
One type of security breach that can flow from non-secure loading of an operating system relates to the protection of the key (or keys) that enable certain restricted functionality. By way of example but not limitation, the MICROSOFT WINDOWS operating systems employ a system key, or “SYSKEY,” that is used to protect various processes by making the correct performance of those processes dependent on the availability of SYSKEY. For example, the key needed to decrypt private information that is stored by the operating system in encrypted form may be derivable from the SYSKEY.
Conventionally, the keys needed to perform restricted operations are protected by the logon procedure. Typically, the user must correctly authenticate himself (e.g., by providing correct logon credentials, such as a username/password combination) prior to commencing use of the system. Use of the keys is enabled only if the user correctly authenticates, and the system will only permit the user a limited number of tries (e.g., three) before concluding that the user has failed to logon properly. (This type of limit on the number of attempts to logon prevents unauthorized users from enabling use of protected functionality by using a brute force attack to guess the password in the case of, say, a stolen laptop computer.) However, using the logon procedure to protect access to keys assumes that the operating system loader correctly loaded the operating system with the correct logon program, and that the use of the keys has not been otherwise enabled by rogue code that may be running. If a rogue loader was used instead, and the rogue loader causes a rogue logon program to be loaded with the operating system, then the use of keys might be enabled, or the keys might even be divulged, without the correct credentials having been entered. Since the loading of the operating system provides an opportunity for a security breach, protection of the keys in such a situation requires that the loading of the operating system take place under circumstances where it can be verified to take place correctly.
One problem that occurs with verifying the security of an operating system load process is that legitimate operating system loads can involve many different programs (e.g., there are numerous different “option ROMs,” which are pre-OS programs that run during a system boot procedure), and there are numerous different procedures that can be performed as part of an operating system load. Thus, there are a nearly uncountable number of different legitimate machine states during a load, and identifying all such states and verifying that the machine is in a known good state may prove to be an infeasible task. However, not all parts of the load procedure have security implications. It may be more efficient to let the load proceed without any attempt to evaluate its security, but then set the environment to a known good state before starting any procedure that could affect a security-related function, such as the distribution of keys. More generally, an arbitrary system can be allowed to run for some time without any type of security evaluation, as long as the system can be set to a known good state before allowing any actions that have security implications to take place.
In view of the foregoing, there is a need for a mechanism that overcomes the drawbacks of the prior art.